//
//  TSImageStoreTool.swift
//  Pods
//
//  Created by 100Years on 2025/6/16.
//
import Kingfisher

private let documentCache: ImageCache = {
    let cache = try! ImageCache(
        name: "default",
        cacheDirectoryURL: FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
    )
    cache.diskStorage.config.expiration = .never // 永不过期
    cache.diskStorage.config.sizeLimit = 0 // 无大小限制
    return cache
}()

public enum TSKFImageCacheType {
    case `default` // cache
    case document

    var imageCache: ImageCache {
        switch self {
        case .document:
            return documentCache
        default:
            return ImageCache.default
        }
    }

    ////        KingfisherManager.shared.cache = TSImageStoreTool.cache
}

public class TSImageStoreTool {
    public static let cache: ImageCache = {
        TSKFImageCacheType.document.imageCache
    }()

    public static func retrieveImageInMemoryCache(urlString: String) -> UIImage? {
        return cache.retrieveImageInMemoryCache(forKey: urlString)
    }

    public static func storeImage(image: UIImage, urlString: String) {
        if let url = URL(string: urlString) {
            cache.store(image, forKey: url.cacheKey)
        }
    }

    public static func removeImage(urlString: String) {
        if urlString.isEmpty {
            return
        }

        if let url = URL(string: urlString) {
            cache.removeImage(forKey: url.cacheKey)
        }
    }

    public static func downloadImageWithProgress(
        urlString: String,
        progressHandler: ((Float) -> Void)? = nil,
        completion: @escaping (UIImage?) -> Void
    ) {
        // 处理非HTTP URL的情况
        if !urlString.contains("http") {
            handleLocalImage(urlString: urlString, completion: completion)
            return
        }

        guard let url = URL(string: urlString) else {
            completion(nil)
            return
        }

        let cacheKey = url.cacheKey

        // 1. 首先尝试从内存缓存获取
        if let memoryImage = cache.retrieveImageInMemoryCache(forKey: cacheKey) {
            completion(memoryImage)
            return
        }

        // 2. 然后尝试从磁盘缓存获取
        cache.retrieveImage(forKey: cacheKey) { result in
            switch result {
            case let .success(value):
                if let diskImage = value.image {
                    // 将从磁盘获取的图片存入内存缓存
                    cache.store(diskImage, forKey: cacheKey, toDisk: false)
                    DispatchQueue.main.async {
                        completion(diskImage)
                    }
                    return
                }

                // 3. 如果缓存中没有，则从网络下载
                downloadFromNetwork(url: url, cacheKey: cacheKey, progressHandler: progressHandler, completion: completion)

            case .failure:
                // 如果磁盘缓存获取失败，也尝试从网络下载
                downloadFromNetwork(url: url, cacheKey: cacheKey, progressHandler: progressHandler, completion: completion)
            }
        }
    }

    /// 获取 Kingfisher 缓存图片的本地磁盘路径
    /// - Parameter urlString: 图片链接
    /// - Returns: 本地缓存图片文件的绝对路径，如果未缓存则返回 nil
    public static func cachedImageDiskPath(for urlString: String) -> String? {
        guard let url = URL(string: urlString) else { return nil }
        let key = url.absoluteString
        let cache = TSImageStoreTool.cache
        let path = cache.cachePath(forKey: key)
        if FileManager.default.fileExists(atPath: path) {
            return path
        } else {
            return nil
        }
    }
    
    public static func cachedImageDiskImage(urlString: String) -> UIImage? {
        if let path = cachedImageDiskPath(for: urlString) {
            return UIImage(contentsOfFile: path)
        }
        return nil
    }

    private static func handleLocalImage(urlString: String, completion: @escaping (UIImage?) -> Void) {
        if urlString.contains("/") {
            completion(UIImage(contentsOfFile: urlString.fillCachePath))
        } else {
            completion(UIImage(named: urlString))
        }
    }

    private static func downloadFromNetwork(
        url: URL,
        cacheKey: String,
        progressHandler: ((Float) -> Void)?,
        completion: @escaping (UIImage?) -> Void
    ) {
        KingfisherManager.shared.retrieveImage(
            with: url,
            options: [.cacheOriginalImage],
            progressBlock: { receivedSize, totalSize in
                let progress = Float(receivedSize) / Float(totalSize)
                DispatchQueue.main.async {
                    progressHandler?(progress)
                }
            },
            completionHandler: { result in
                DispatchQueue.main.async {
                    switch result {
                    case let .success(value):
                        // 将下载的图片存入缓存
                        cache.store(value.image, forKey: cacheKey)
                        completion(value.image)
                    case .failure:
                        completion(nil)
                    }
                }
            }
        )
    }

    /// 从 KF的换从中取图片
    /// - Parameters:
    ///   - urlString: url
    ///   - progressHandler: progressHandler
    ///   - completion: completion
    public static func retrieveImage(
        urlString: String,
        progressHandler: ((Float) -> Void)? = nil,
        completion: @escaping (UIImage?) -> Void
    ) {
        guard let url = URL(string: urlString) else {
            completion(nil)
            return
        }

        KingfisherManager.shared.retrieveImage(
            with: url,
            options: [],
            progressBlock: { receivedSize, totalSize in
                let progress = Float(receivedSize) / Float(totalSize)
                DispatchQueue.main.async {
                    progressHandler?(progress)
                }
            },
            completionHandler: { result in
                DispatchQueue.main.async {
                    switch result {
                    case let .success(value):
                        completion(value.image)
                    case .failure:
                        completion(nil)
                    }
                }
            }
        )
    }
}
